/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.sunrise.boundary;

import com.sunrise.entity.Calendar;
import com.sunrise.entity.Event;
import com.sunrise.entity.Location;
import com.sunrise.entity.User;
import java.util.List;
import javax.ejb.EJB;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.UserTransaction;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.runner.RunWith;

/**
 *
 * @author frank
 */
@RunWith(Arquillian.class)
public class UserManagerIT {
    
    @PersistenceContext
    EntityManager em;
    
    @Inject
    UserTransaction utx;
    
    @Deployment
    public static WebArchive createArchiveAndDeploy() {
        Class[] classes = {
            UserManager.class,
            Event.class,
            User.class,
            Calendar.class,
            Location.class,
        };

        WebArchive arch = ShrinkWrap.create(WebArchive.class);
        for (Class c : classes) {
            arch.addClass(c);
        }

        return arch.addPackage(User.class.getPackage())
                .addPackage(EventManager.class.getPackage())
                .addAsResource("test-persistence.xml", "META-INF/persistence.xml")
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
    }
    
    
    @Before
    public void setUp() throws Exception {
        clearData();
        insertData();
        startTransaction();
    }

    private User[] TEST_USERS;
    
    @EJB
    UserManager cut;
    
    @Test
    public void testSave() throws Exception {
        User user = TEST_USERS[0];
        cut.save(user);
        
        assertTrue(isUserInDB(user));
    }

    @Test
    public void testUnregister() throws Exception {
        User user1 = TEST_USERS[0];
        User user2 = TEST_USERS[1];
        cut.save(user1); cut.save(user2);
        
        cut.unregister(user2);
        
        assertTrue(isUserInDB(user1));
        assertFalse(isUserInDB(user2));
    }

    @Test
    public void testFindUserById() throws Exception {
        User toBeFound = TEST_USERS[0];
        cut.save(toBeFound); cut.save(TEST_USERS[1]); cut.save(TEST_USERS[2]);
        
        User u = cut.findUserById(toBeFound.getId());
        assertEquals(toBeFound, u);
    }

    @Test
    public void testFindUserByEmail() throws Exception {
        User toBeFound = TEST_USERS[0];
        
        saveTestUsers();
        User res = cut.findUserByEmail(toBeFound.getEmail());
        
        assertEquals(res, toBeFound);
    }

    @Test
    public void testNewUserGetsNewCalendarByDefault() throws Exception {
        User u = new User("martina", "verdi", "mv@gmail.com", "123456");
        cut.save(u);
        
        //calendar created
        assertEquals(u.getCalendars().size(), 1);
        // calendar is private by default
        assertFalse(u.getCalendars().get(0).isPublicCalendar());
    }
    
    // utility
    
    private boolean isUserInDB(User user) {
        List<User> allUsers;
        allUsers = (List<User>)em.createQuery("SELECT u from User u")
                .getResultList();
        return allUsers.contains(user);
    }
    
    private void saveTestUsers() {
        for (User u : TEST_USERS) {
            cut.save(u);
        }
    }

    // db
    
    private void clearData() throws Exception {
        utx.begin();
        em.joinTransaction();
        em.createQuery("delete from Calendar").executeUpdate();
        em.createQuery("delete from User").executeUpdate();
        utx.commit();
        em.clear();
        
        TEST_USERS = null;
    }

    private void insertData() throws Exception {
        TEST_USERS = new User[]{
            new User("francesco", "di lorenzo", "test123@gmail.com", "pass123"),
            new User("andrea", "bellotti", "abc@gmail.com", "pass123"),
            new User("paolo", "rossi", "paolo.rossi@polimi.com", "pass123"),
        };
    }

    private void startTransaction() throws Exception {
        utx.begin();
        em.joinTransaction();
    }

    @After
    public void commitTransaction() throws Exception {
        utx.commit();
    }
}
